在前一天我們 介紹到Replication Controller 。如果讀者看過 Replication Controller官方文件 ,可以看到官方在文件一開頭就表示:
NOTE: A Deployment that configures a ReplicaSet is now the recommended way to set up replication.
正如昨天所提,雖然 Replication Controller 雖然看似幫我們解決Pod scaling的問題,然而在實際場景上的應用是不夠的。
若是回溯 DevOps 的歷史,可以發現 DevOps 與 Agile敏捷開發 可以說是密不可分,最早 DevOps 一詞也是從 Agile社群中被提出,如果讀者對於這段歷史有興趣,不妨看看 Youtuber 上的一段影片 The History of DevOps,會更了解DevOps與Agile之間的關係。而在 Agile 社群中其中一個精神便是如何正確收集到使用者需求以及快速的回應
,頻繁的系統升級(Rollout)
更是不可避免的。而對於運維人員,如何在頻繁更新一個服務時做到每次都能zero downtime(無停機服務遷移)
更是一大挑戰。幸好,這些 Kubernetes 都幫我們做好了。
Kubernetes 官方提供我們 Deployment 元件,不只能幫我們做到Pod scaling,對於 應用服務的rollout與rollback的支援也非常豐富。今天學習筆記內容如下:
小提醒:今天的程式碼都可以在 demo-deployment 上找到。
Replica Sets 可以說是進化版的 Replication Controller,與 Replication Controller最大的差異在於,Replica Sets 提供了更彈性的selector
。
以 my-replica-sets.yaml 為例
不同於 Replication Controller 的 selector,只能用等於
的符號表示,Replica Set 的 selector 支援更多複雜的條件過濾。
app/v1
;如果版本號是在1.9以前的話,則需使用apps/v1beta2
matchLabels
,matchLabels的用法代表著等於(equivalent)
,代表Pod的labels必須與matchLabels
中指定的值相同,才算符合條件。matchExpressions
的用法較為彈性,每一筆條件主要由三個部分組成key
, operator
,value
。以 my-replica-sets.yaml 中敘述為例,我們指定Pod的條件為 1) env必須為dev 2) env不能為prod。而目前operator
支援4種條件In
, NotIn
, Exists
, 以及 DoesNotExis
,更多關於matchExpressions
的運用可以參考 官方文件
Replica Set 與昨天提到的Replication Controller 的kubectl指令相似,可以參考 昨日Replication Controller學習筆記
而在 Kubernetes官方文件 中也提到,雖然Replica Set提供更彈性的selector,並不推薦開發者直接使用kubectl create
等指令創建Replica Set 物件,而是透過 Deployment 來創建新的 Replica Set。
Deployment 可以幫我們達成以下幾件事情:
以下,是我們今天會使用到的 my-deployment.yaml
apiVersion: apps/v1beta2 # for kubectl versions >= 1.9.0 use apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-deployment
template:
metadata:
labels:
app: my-deployment
spec:
containers:
- name: my-pod
image: zxcvbnius/docker-demo:latest
ports:
- containerPort: 3000
Deployment yaml 檔的寫法與 Replica Sets 相似,如果kubectl的版本 >= 1.9,則需使用app/v1
;如果版本號是在1.9以前的話,則需使用apps/v1beta2
,可以用kubectl version
查看目前的版本號,
由於筆者目前仍使用
1.8
的版本,所以apiVersion仍需使用apps/v1beta2
。
接著我們可以使用kubectl create
指令來新建一個 Deployment 物件,
$ kubectl create -f ./my-deployment.yaml
deployment "hello-deployment" created
用kubectl get
查看deployment與Pod的狀態,
可以發現 Deployment已自動幫我們創建Pod,且這個Pod都帶有app=my-deployment的label,而在同時,Deployment也會自動幫我們建立一個Replication Set
來管理這些Pod
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
hello-deployment-6577d8cc46 3 3 3 22m
在開始實作之件,想先分享幾個常見的指令:
Deployment相關指令 | 指令功能 |
---|---|
kubectl get deployments | 取得目前Kubernetes中的deployments的資訊 |
kubectl get rs | 取得目前Kubernetes中的Replication Set的資訊 |
kubectl describe deploy <deployment-name> | 取得特定deployment的詳細資料 |
kubectl set image deploy/ <deployment-name> <pod-name>: <image-path>: <version> | 將deployment管理的pod升級到特定image版本 |
kubectl edit deploy <deployment-name> | 編輯特定deployment物件 |
kubectl rollout status deploy <deployment-name> | 查詢目前某deployment升級狀況 |
kubectl rollout history deploy <deployment-name> | 查詢目前某deployment升級的歷史紀錄 |
kubectl rollout undo deploy <deployment-name> | 回滾Pod到先前一個版本 |
kubectl rollout undo deploy <deployment-name> --to-revision=n | 回滾Pod到某個特定版本 |
接下來,將會根據上面幾個常用指令,在我們本機端的環境中進行實際操作。
相信眼尖的讀者發現,若是要取得在Kuberntes的物件資訓,都是透過kubectl get
指令。如果想要看Kubernetes Cluster中所有目前已被建立的物件,可以使用kubectl get all
一次取得所有資訊。
若是對於指令還不太熟悉,也可以在終端機輸入kubectl get
,如此便能得到Kubernetes目前所有提供的元件型別
以及每個元件型別支援的縮寫格式
。
$ kubectl get
You must specify the type of resource to get. Valid resource types include:
* all
* certificatesigningrequests (aka 'csr')
* clusterrolebindings
...
* pods (aka 'po')
...
為了實作如何利用Deployment 升級web app
,筆者預先將先前 demo 用的 web application v2版本上傳到 Docker Hub,在v2
的版本中,收到request之後會回傳Hello World! v2
而在上面,我們使用kubectl create
創建好一個Deployment物件之後,我們可以先創建一個 Service 來測試是否我們創建的web app有正常運作。
$ kubectl expose deploy hello-deployment --type=NodePort --name=my-deployment-service
service "my-deployment-service" exposed
創建好之後,我們可以透過minikube server
取得目前my-deployment-service
的網址,
$ minikube service my-deployment-service --url
http://192.168.99.100:30390
接著我們可以在本機端的瀏覽器訪問 http://192.168.99.100:30390
可以看到web app正常運作中。接著我們可以透過docker set image
來rollout我們的 web app
$ kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo:v2.0.0
deployment "hello-deployment" image updated
這時我們也可以使用kubectl rollout status
來查詢目前升級的狀態
$ kubectl rollout status deploy hello-deployment
deployment "hello-deployment" successfully rolled out
可以看到 deployment hello-deployment 已成功升級完成。
如果再重新訪問一次 http://192.168.99.100:30390,可以看到瀏覽器的畫面變成Hello World! v2
了!
如果在升級的過程中,查看kubectl get pod
,會發現Deployment在升級web app時,並不會把原本的pod直接砍掉,而是會另外生成Pod來取代原本Pod,來達到無痛升級的需求(zero downtime)。也就是說,在我們的Kubernetes Cluster中同時間會存在6個Pod。
如果不想要同時間存在這麼多Pod,我們可以在Deployment的設定檔中指定strategy.rollingUpdate.maxSurge的數量。在今日學習筆記中後段,會介紹如何設定maxSurge
。
除了透過kubectl set image
更新Pod的image之外,我們也可以透過kubectl edit
來進行更新,輸入以下指令
$ kubectl edit deploy hello-deployment
除了可以看到原先的我們設定的欄位以外,也會發現多了幾個不一樣的欄位。
strategy
Kubernetes為了讓我們可以確保rollout的時候,按照我們所想的方式。所以在Deployment Configuration中,有一個strategy的設定值,可以將我們希望行為放在裡面。
strategy.rollingUpdate.maxSurge
maxSurge可以是百分比數
,也可以是數字
。代表在rollout的過程中,最多可以比原先指定的Pod數量多出多少。好比原本replicas為3
,maxSurge為1
,代表在升級的過程中,deployment頂多會多產生一個Pod。
strategy.rollingUpdate.maxUnavailable
代表在升級過程中,可以容忍多少Pod無法使用,如果maxSurge
的數字非0的話,maxUnavailable
的數字也不能為0。
最後,我們可以透過kubectl rollout history
來查該Deployment看過去rollout的紀錄
可以看到過去hello-deployment
總共經歷2次的rollout。一次是我們第一次創建Deployment的時候,一次是我們升級成v2
版本的時候。而若是kubectl set image
指令結尾加上 --record
,CHANG-CAUSE
可以紀錄我們每次rollout的指令。例如,我們希望將Pod“升級”到latest版本。
$ kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo --record
deployment "hello-deployment" image updated
可以看到CHANGE-CAUSE
多了紀錄,之後如果我們想要revert
到特定版本,也可以根據CHANGE-CAUSE
來決定。
如果我們想要把目前版本rollback
到上一版,我們可以使用kubectl rollout undo
$ kubectl rollout undo deployment hello-deployment
deployment "hello-deployment" rolled back
如果這時再去檢查kubectl rollout history
,會發現多了一個版本
$ kubectl rollout history deploy hello-deployment
deployments "hello-deployment"
REVISION CHANGE-CAUSE
1 <none>
3 kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo --record=true
4 <none>
最後,要介紹的是如何rollback回到特定版本,已回滾到REVISION 3
為例,可以使用以下指令
$ kubectl rollout undo deploy hello-deployment --to-revision=3
在rollback成功之後,若是再次查詢kubectl rollout history
會發現又多了一個REVISION
囉。
以上,是今天學習筆記中想跟大家分享 Deployment 的部分。雖然今天的學習筆記無法分享Deployment的其他用途,但光是rollup
與rollback
相信讀者也可以感受到Deployment的強大。而在明天的學習筆記中,將會分享我們在過去幾天中常提及的Kubernetes的元件 - Service 。
如果對於A/B test有興趣的朋友,可以參考官網提供的 Canary Deployment ,相信會有不少的收穫。
依舊歡迎大家給予建議與討論,如果能按個讚給些鼓勵也是很開心唷 : )
感謝大大的認真教學,這系列真的學到很多
.
expose完第一次rollout那邊
「可以看到web app正常運作中。接著我們可以透過docker set image
來rollout我們的 web app」
應該改為kubectl set image